﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityGameFramework.Runtime;
using StarForce.Tool;
using GameFramework.Fsm;

namespace StarForce {
    [RequireComponent(typeof(Collider),typeof(IMouseInput),typeof(Rigidbody))]
    public class Card : Entity
    {
        /// <summary>
        /// 组件
        /// </summary>
        #region Components
        public UiMotionBaseCard Scale { get; private set; }
        public UiMotionBaseCard Rotation { get; private set; }
        public UiMotionBaseCard Movement { get; private set; }
        public SpriteRenderer SpriteRenderer { get; private set; }
        public SpriteRenderer[] SpriteRenderers { get; private set; }
        public PlayerHand Hand { get; private set; }
        public Collider Collider { get; private set; }
        public IMouseInput Input { get; private set; }
        public Rigidbody Rigidbody { get; private set; }
        public MonoBehaviour MonoBehaviour { get; private set; }
        public Transform transform = null;
        public IFsm<Card> Fsm = null;
        public Camera MainCamera => Camera.main;
        #endregion
        
        /// <summary>
        /// 数据
        /// </summary>
        #region Data

        [SerializeField] private CardData m_CardObjectData;

        public FsmState<Card> currentCardState = null;

        #endregion

        /// <summary>
        /// 事件函数
        /// </summary>
        /// <param name="userData"></param>
        #region EventFunction

#if UNITY_2017_3_OR_NEWER
        protected override void OnInit(object userData)
#else
        protected internal override void OnInit(object userData)
#endif
        {
            base.OnInit(userData);
            gameObject.SetLayerRecursively(Constant.Layer.BaseCardObjectLayerId);
        }
        
#if UNITY_2017_3_OR_NEWER
        protected override void OnShow(object userData)
#else
        protected internal override void OnShow(object userData)
#endif
        {
            base.OnShow(userData);

            m_CardObjectData = userData as CardData;
            if (m_CardObjectData == null)
            {
                Log.Error("BaseCard object data is invalid.");
                return;
            }
            var gameObject = this.gameObject;
            transform = gameObject.transform;
            MonoBehaviour = this;
            Input = GetComponent<IMouseInput>();
            Collider = GetComponent<Collider>();
            Rigidbody = GetComponent<Rigidbody>();
            Scale = new UiMotionScaleCard(this);
            Rotation = new UiMotionRotationCard(this);
            Movement = new UiMotionMovementCard(this);
            SpriteRenderer = this.gameObject.GetComponentInChildren<SpriteRenderer>();
            SpriteRenderers = this.gameObject.GetComponentsInChildren<SpriteRenderer>();
            InitInfo();
            CreateFSM();
            StartFSM();
        }

        private void InitInfo() {
            Name = m_CardObjectData.CardName;
            transform.localScale = new Vector3(m_CardObjectData.CardSize.x,
                m_CardObjectData.CardSize.y,this.gameObject.transform.localScale.z);
            transform.localPosition = Vector3.zero;
            Hand = m_CardObjectData.PlayerHand;
        }

        private void CreateFSM() {
            Fsm = GameEntry.Fsm.CreateFsm<Card>(this.GetHashCode().ToString(),this,
                new CardIdleState(this,m_CardObjectData.Parameters),
                new CardDrawState(this,m_CardObjectData.Parameters),
                new CardDragState(this,m_CardObjectData.Parameters),
                new CardHoverState(this,m_CardObjectData.Parameters),
                new CardSelectState(this,m_CardObjectData.Parameters),
                new CardDiableState(this,m_CardObjectData.Parameters),
                new CardDiscardState(this,m_CardObjectData.Parameters)
            );
        }

        private void StartFSM() {
            Fsm.Start<CardDrawState>();
            currentCardState = Fsm.CurrentState;
        }

        private void Update() {
            Scale?.Update();
            Rotation?.Update();
            Movement?.Update();
        }

        #endregion

        /// <summary>
        /// 操作
        /// </summary>
        #region Operator

        public void MoveTo(Vector3 postion, float speed, float delay = 0) => Movement.Execute(postion, speed, delay);
        public void MoveToWithZ(Vector3 postion, float speed, float delay = 0) => Movement.Execute(postion, speed, delay,true);
        public void RotateTo(Vector3 rotation,float speed,float delay = 0) => Rotation.Execute(rotation,speed,delay);
        public void ScaleTo(Vector3 scale, float speed, float delay = 0) => Scale.Execute(scale, speed, delay);

        public void Select() {
            
        }

        #endregion
        
    }
}

